package com.fsnbigdata.web;
import com.fsnbigdata.domain.AnimalConservation;
import com.fsnbigdata.domain.Document;
import com.fsnbigdata.domain.query.AnimalConservationQueryDslBinder;
import com.fsnbigdata.domain.query.DocumentQueryDslBinder;
import com.fsnbigdata.enums.ResultEnum;
import com.fsnbigdata.exception.ParamException;
import com.querydsl.core.types.Predicate;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiParam;
import java.security.Principal;
import javax.print.Doc;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.querydsl.binding.QuerydslPredicate;
import org.springframework.roo.addon.web.mvc.controller.annotations.ControllerType;
import org.springframework.roo.addon.web.mvc.controller.annotations.RooController;
import org.springframework.roo.addon.web.mvc.controller.annotations.responses.json.RooJSON;
import com.fsnbigdata.service.api.DocumentService;
import io.springlets.data.domain.GlobalSearch;
import java.util.Collection;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
import org.springframework.web.util.UriComponents;
import springfox.documentation.annotations.ApiIgnore;

/**
 * = DocumentsCollectionJsonController
 *
 * TODO Auto-generated class documentation
 *
 */
@RooController(entity = Document.class, pathPrefix = "/api", type = ControllerType.COLLECTION)
@RooJSON
@RestController
@RequestMapping(value = "/api/documents", name = "DocumentsCollectionJsonController", produces = MediaType.APPLICATION_JSON_VALUE)
@Api(tags = "Document", description = "参考文献" )
public class DocumentsCollectionJsonController {

    /**
     * TODO Auto-generated attribute documentation
     *
     */
    private DocumentService documentService;

    /**
     * TODO Auto-generated constructor documentation
     *
     * @param documentService
     */
    @Autowired
    public DocumentsCollectionJsonController(DocumentService documentService) {
        this.documentService = documentService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return DocumentService
     */
    public DocumentService getDocumentService() {
        return documentService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param documentService
     */
    public void setDocumentService(DocumentService documentService) {
        this.documentService = documentService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param query
     * @param pageable
     * @return ResponseEntity
     */
    @GetMapping(name = "search", value = "search")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "page", defaultValue = "0", dataType = "int", paramType = "query"),
        @ApiImplicitParam(name = "size", defaultValue = "20", dataType = "int", paramType = "query")
    })
    public ResponseEntity<Page<Document>> search(
        @ApiParam @RequestParam(required = false) String query,
        Pageable pageable) {
        GlobalSearch globalSearch = StringUtils.isNotBlank(query) ? new GlobalSearch(query, false) : null;
        Page<Document> documents = getDocumentService().findAll(globalSearch, pageable);
        return ResponseEntity.ok(documents);
    }

    /**
     *
     * @param predicate
     * @param pageable
     * @return
     */
    @GetMapping(name = "search", value = "advanceSearch")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "page", defaultValue = "0", dataType = "int", paramType = "query"),
        @ApiImplicitParam(name = "size", defaultValue = "20", dataType = "int", paramType = "query")
    })
    public ResponseEntity<Page<Document>> advanceSearch(
        @ApiParam @QuerydslPredicate(root = Document.class, bindings = DocumentQueryDslBinder.class) Predicate predicate,
        Pageable pageable) {
        Page<Document> documents = getDocumentService().search(predicate, pageable);
        return ResponseEntity.ok(documents);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param query
     * @param pageable
     * @return ResponseEntity
     */
    @GetMapping(name = "list")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "page", defaultValue = "0", dataType = "int", paramType = "query"),
        @ApiImplicitParam(name = "size", defaultValue = "20", dataType = "int", paramType = "query")
    })
    @PreAuthorize("hasRole('DB_DOCUMENT')")
    public ResponseEntity<Page<Document>> list(
        Authentication authentication,
        @ApiParam @RequestParam(required = false) String query,
        Pageable pageable) {
        GlobalSearch globalSearch = StringUtils.isNotBlank(query) ? new GlobalSearch(query, false) : null;
        Page<Document> documents = null;
        documents = getDocumentService().findAll(globalSearch, pageable);
        return ResponseEntity.ok(documents);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return UriComponents
     */
    public static UriComponents listURI() {
        return MvcUriComponentsBuilder.fromMethodCall(MvcUriComponentsBuilder.on(DocumentsCollectionJsonController.class).list(null,null, null)).build().encode();
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param document
     * @param result
     * @return ResponseEntity
     */
    @PostMapping(name = "create")
    @PreAuthorize("hasRole('DB_DOCUMENT')")
    public ResponseEntity<?> create(
        @Valid @RequestBody Document document,
        BindingResult result,
        Principal principal) {
        if (document.getId() != null || document.getVersion() != null) {
            return ResponseEntity.status(HttpStatus.CONFLICT).build();
        }
        if (result.hasErrors()) {
            throw new ParamException(ResultEnum.PARAM_ERROR.getCode(),
                    result.getFieldError().getDefaultMessage());
        }

        document.setCreator(principal.getName());

        Document newDocument = getDocumentService().save(document);
        //UriComponents showURI = DocumentsItemJsonController.showURI(newDocument);
        return ResponseEntity.ok(newDocument);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param documents
     * @param result
     * @return ResponseEntity
     */
    @PostMapping(value = "/batch", name = "createBatch")
    @ApiIgnore
    public ResponseEntity<?> createBatch(@Valid @RequestBody Collection<Document> documents, BindingResult result) {
        if (result.hasErrors()) {
            return ResponseEntity.status(HttpStatus.CONFLICT).body(result);
        }
        getDocumentService().save(documents);
        return ResponseEntity.created(listURI().toUri()).build();
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param documents
     * @param result
     * @return ResponseEntity
     */
    @PutMapping(value = "/batch", name = "updateBatch")
    @ApiIgnore
    public ResponseEntity<?> updateBatch(@Valid @RequestBody Collection<Document> documents, BindingResult result) {
        if (result.hasErrors()) {
            return ResponseEntity.status(HttpStatus.CONFLICT).body(result);
        }
        getDocumentService().save(documents);
        return ResponseEntity.ok().build();
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param ids
     * @return ResponseEntity
     */
    @DeleteMapping(value = "/batch/{ids}", name = "deleteBatch")
    @ApiIgnore
    public ResponseEntity<?> deleteBatch(@PathVariable("ids") Collection<Long> ids) {
        getDocumentService().delete(ids);
        return ResponseEntity.ok().build();
    }
}
